﻿using Sustainalytics.ClientDW.DataAccessLayer.ESGRatings;
using Sustainalytics.DataLayer.EsgRatings;
using Sustainalytics.DataLayer.Shared;
using Sustainalytics.Entities;
using Sustainalytics.Entities.ESGRatings;
using Sustainalytics.Utils;
using System;
using System.Collections.Generic;
using System.Linq;

namespace Sustainalytics.EsgRatings.BusinessLogic
{
    public class WeightMatricesManagement : IWeightMatricesManagement
    {
      
        private readonly IEsgInputFileRepository _esgInputFileRepository;
        private readonly IWeightMatricesRepository _weightMatricesRepository;
        private readonly IRepositoryCollection<ESGProfile> _esgProfileRepository;
        private readonly IRepositoryCollection<Account> _accountRepository;

        private WeightMatricesManagement(
                                            IEsgInputFileRepository esgInputFileRepository,
                                            IWeightMatricesRepository weightMatricesRepository,
                                            IRepositoryCollection<ESGProfile> esgProfileRepository,
                                            IRepositoryCollection<Account> accountRepository
                                            )
        {
            _esgInputFileRepository = esgInputFileRepository;
            _weightMatricesRepository = weightMatricesRepository;
            _esgProfileRepository = esgProfileRepository;
            _accountRepository = accountRepository;

        }




        public static IWeightMatricesManagement GetInstance(
                                                            IEsgInputFileRepository esgInputFileRepository,
                                                            IWeightMatricesRepository weightMatricesRepository,
                                                            IRepositoryCollection<ESGProfile> esgProfileRepository,
                                                            IRepositoryCollection<Account> accountRepository
                                                          )
        {
           
            if (esgInputFileRepository == null)
            {
                throw new ArgumentException("No instance of IEsgInputFileRepository provided for creating an IWeightMatricesManagement!");
            }

            if (weightMatricesRepository == null)
            {
                throw new ArgumentException("No instance of IWeightMatricesRepository provided for creating an IWeightMatricesManagement!");
            }

            if (esgProfileRepository == null)
            {
                throw new ArgumentException("No instance of IRepositoryCollection<ESGProfile> provided for creating an IWeightMatricesManagement!");
            }

            if (accountRepository == null)
            {
                throw new ArgumentException("No instance of IRepositoryCollection<Account> provided for creating an IWeightMatricesManagement!");
            }


            return new WeightMatricesManagement( esgInputFileRepository, weightMatricesRepository, esgProfileRepository, accountRepository);
        }

       


        public List<WeightMatrix> GetActiveWeightMatrices()
        {
            IEnumerable<WeightMatrix> result = _weightMatricesRepository.ListWeightMatrices();
            result = result.Where(a => a.MarkedForDeletionOn == null);
            return result.IsNullOrEmpty() ? new List<WeightMatrix>() : result.ToList();
        }

     

        public List<EsgInputFileComplete> ListEsgInputFilesByAccountId(Guid? accountId)
        {
            var result = _esgInputFileRepository.ReadEsgInputFilesByAccountId(EsgInputFileType.WeightMatrix, accountId).ToList();
            return result;
        }

        public List<WeightMatrix> ListWeightMatricesByAccountId(Guid? accountId, bool includeDetails = false)
        {
            return _weightMatricesRepository.ListWeightMatricesByAccountId(accountId, includeDetails);
        }

        public int CountWeightMatricesByAccountId(Guid? accountId)
        {
            return _weightMatricesRepository.CountWeightMatricesByAccountId(accountId);
        }

        public int GetMatricesSlotsPerPlatform()
        {
            List<WeightMatrix> defWMatrixList = ListWeightMatricesByAccountId(null);
            WeightMatrix defWMatrix = null;

            if (defWMatrixList.Any())
            {
                defWMatrix = defWMatrixList.FirstOrDefault();
            }

            int count = 0;
            var activeAccounts = _accountRepository.ReadAllWhere(a => (a.Status == Status.Active) && a.PlatformTier == AccessLevel.Tier1 || a.PlatformTier == AccessLevel.Tier2);

            activeAccounts.ToList().ForEach((x) =>
            {
                if (x.PlatformTier == AccessLevel.Tier1)
                {
                    count += this.CountWeightMatricesByAccountId(x.Id);
                }

                if (x.PlatformTier == AccessLevel.Tier2)
                {
                    List<ESGProfile> esgProfileEntities = _esgProfileRepository.ReadWhere(ep => ep.AccountId == x.Id && ep.Active == ActiveTypeEnum.Active).ToList();
                    if (esgProfileEntities.Any())
                    {
                        ESGProfile defProfile = esgProfileEntities.FirstOrDefault();
                        if (defProfile.MatrixId != defWMatrix.Id) { count++; } //we don't need to count if it's the default weight matrix
                    }
                }
            });

            return count;
        }

        public WeightMatrix GetWeightMatrix(Guid matrixId)
        {
            WeightMatrix wm = _weightMatricesRepository.GetWeightMatrix(matrixId);
            return wm;
        }

        public WeightMatrix UpdateCustomWeightMatrix(WeightMatrix wm)
        {
            _weightMatricesRepository.SaveWeightMatrix(wm);
            WeightMatrix wmUpdated = _weightMatricesRepository.GetWeightMatrix(wm.Id);

            return wmUpdated;
        }

        public void DeleteCustomWeightMatrix(Guid matrixId)
        {
            WeightMatrix wm = _weightMatricesRepository.GetWeightMatrix(matrixId);

            if (wm == null)
                return;

            wm.MarkedForDeletionOn = DateTime.Now;

            // remove news items
            _weightMatricesRepository.SaveWeightMatrix(wm);
        }

        public List<string> DeleteCustomWeightMatrices()
        {
            var activityLog = new List<string>();

            // take only custom weight matrixes marked for deletion
            var weightMatrices = _weightMatricesRepository.ListWeightMatrices()
                .Where(wm => wm.AccountId.HasValue && wm.MarkedForDeletionOn.HasValue)
                .ToList();

            activityLog.Add("Weight matrices to delete: " + weightMatrices.Count + Environment.NewLine);

            foreach (var wm in weightMatrices)
            {
                _weightMatricesRepository.DeleteCompaniesWeights(wm.Id);

                _weightMatricesRepository.DeletePeerGroupsWeights(wm.Id);

                _weightMatricesRepository.DeleteWeightMatrix(wm.Id);
            }

            activityLog.Add("Deleted weight matrices: " + Environment.NewLine +
                            string.Join(Environment.NewLine, weightMatrices.Select(wm =>
                                string.Format("WeightMatrixId: {0}, AccountId {1}", wm.Id, wm.AccountId)))
                );

            return activityLog;
        }


    }

}
